iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 28
0
Modern Web

再談 PixiJS,那些先前不一定有提到的部分與地雷系列 第 28

[Re:PixiJS - Day28] Loader 的其他特性

  • 分享至 

  • xImage
  •  

補充幾個 Loader 的特性:

1. 在讀取完成前無法使用 add() 讀取下一個檔案:

[ Demo-1 ]

const loader = PIXI.Loader.shared;
loader.add('bunny', 'assets/basics/bunny.png');

loader.load((loader, resources) => {
    // console.log("loader: ", loader, " resources: ", resources);
    console.log('complete');
});

// 在讀取完成前再使用 .add() 一次
loader.add('bunny', 'assets/basics/bunny.png');

2. 稱無法重複使用 相同的resource 名稱:

[ Demo-2 ]

const loader = PIXI.Loader.shared;
loader.add('bunny', 'assets/basics/bunny.png');

// 圖取不同圖片,可是素材名都命名為 'bunny'
loader.add('bunny', 'assets/basics/bunny2.png');

loader.load((loader, resources) => {
    console.log('complete');
});

PixiJS 使用 Loader 時,可不指定讀入的 素材名稱
此時會以讀入的素材 url 命名

例如:

const loader = PIXI.Loader.shared;
loader.add('assets/basics/bunny.png');
loader.load();

結果為:


3. 重複讀取已經讀取過的 TextureCache / BaseTextureCache,會跳 console.warn():

[ Demo-3 ]

const loader = PIXI.Loader.shared;
loader.add('bunny', 'assets/basics/bunny.png');

// 更改了素材名,但 url 相同
loader.add('bunny2', 'assets/basics/bunny.png');

loader.load((loader, resources) => {
    console.log('complete');
});

前半小結:
Loader 的 Resource 快取與 textureCache / baseTextureCache 某方面來說有點像,
但是是不同的東西


PIXI.Sprite 與 PIXI.AnimatedSprite 的快取比較

[ Demo-4 ]
使用 PIXI.Sprite.from() 時,會自動檢查是否有快取
如果已有快取,便不會再送 Request

  • TextureCache / BaseTextureCache 不會增加

  • 不會再送 Request

function createBunny(){
    const bunny = PIXI.Sprite.from('assets/basics/bunny.png');
    bunny.anchor.set(0.5);
    return bunny;
};

setInterval(() => {
    const bunny = createBunny();
    bunny.x = Math.random() * app.screen.width;
    bunny.y = Math.random() * app.screen.height;

    app.stage.addChild(bunny);
}, 1000);

同理可先使用 Loader 將兔子圖片讀入,確保隨後使用 PIXI.Sprite.from() 時,
不會因為沒有快取而產生讀取時間
[ Demo-5 ]

const loader = PIXI.Loader.shared;
loader.add('assets/basics/bunny.png');

loader.load((loader, resources) => {
    console.log('complete');
    startApp();
});

function startApp(){
    setInterval(() => {
        const bunny = createBunny();
        bunny.x = Math.random() * app.screen.width;
        bunny.y = Math.random() * app.screen.height;

        app.stage.addChild(bunny);
    }, 1000);
};

PIXI.Sprite.from()讀取處理快取 相當方便的方法
但是 PIXI.AnimatedSprite 沒有這麼方便的方法可 同時處理讀取與快取

昨天的文章裡提到 PIXI.AnimatedSprite 裡帶入素材陣列的兩種方式:
1- 手動帶入素材陣列
2- 使用已整理成 PIXI.Spritesheet 物件裡的 animation

兩種方式皆為 已確定讀入素材快取 的前提下發生的

也就是說,沒有 PIXI.AnimatedSprite 的 from( filename.json ) 的方式
可以同時處理讀取 JSON讀取各個 Texture / BaseTexrue處理快取的方法

PIXI.AnimatedSprite.fromFrames()PIXI.AnimatedSprite.fromImages() 都是在 已有快取已知素材名的前提下使用,與 先讀.json 後再 讀取圖片 的方式不同


聽起來好像還好啊?

[ Demo-6 ] - 產生一個 loop 播放的兔子

function createAnimatedBunny() {
    loader.add('bunniesSpritesheet', 'bunnies.json');
    loader.load((loader, resources) => {
        const bunnySpritesheet = resources.bunniesSpritesheet.spritesheet;
        const animateBunny = new PIXI.AnimatedSprite(bunnySpritesheet.animations.bunny);
        // 省略一些 bunnySpritesheet 的設定
        app.stage.addChild(animateBunny);
    });
};
createAnimatedBunny();

重複呼叫 createAnimatedBunny() 的話開始有問題了


因為 loader.add('bunniesSpritesheet', 'bunnies.json'); 的 bunniesSpritesheet 重複

function createAnimatedBunny() {
    loader.add(`bunniesSpritesheet`, 'bunnies.json');
    loader.load((loader, resources) => {
        const bunnySpritesheet = resources.bunniesSpritesheet.spritesheet;
        const animateBunny = new PIXI.AnimatedSprite(bunnySpritesheet.animations.bunny);
        // 省略一些 bunnySpritesheet 的設定
        app.stage.addChild(animateBunny);
    });
};
createAnimatedBunny();

改一下 Resource Name,讓呼叫 createAnimatedBunny() 時不會因為素材名稱相同出錯:

function createAnimatedBunny() {
    // 動態改素材名
    const spritesheetName = `Spritesheet${Math.random()* 1000}`;
    loader.add(spritesheetName, 'bunnies.json');
    loader.load((loader, resources) => {
        const bunnySpritesheet = resources[spritesheetName].spritesheet;
        const animateBunny = new PIXI.AnimatedSprite(bunnySpritesheet.animations.bunny);
      
        app.stage.addChild(animateBunny);
    });
};

雖然可以重複呼叫 createAnimatedBunny(),可是接著有兩個問題:
1- TextureCache / BaseTextureCache 重複
2- Resource 沒快取了

發生原因: Texture / BaseTexture 的原始檔都有檢查是否有重複的 cacheId
重複時會出現 console.warn();

由於一組 Spritesheet 通常 不會只有一兩張 Texture
因此因為讀取 Spritesheet 的 .JSON 檔時出現的 console.warn(); 通常都是一整片
可能還需要將 console.warn(); 過濾掉,很不方便。

console頁籤 點選下拉選單,可以將 console.warn(); 關掉


還有一種做法是每次要 呼叫 Loader 時,就把所有快取清掉


clearTextureCache() 與 destroyTextureCache() 差異:

從結果來看,TextureCache / BaseTextureCache 的結果是相同的,
差別在:正在使用 Texture / BaseTexture 的元件會 出現錯誤

  • 使用 clearTextureCache() 後,原本的兔子還在,但 TextureCache / BaseTextureCache 清除了

  • 使用 destroyTextureCache() 後,由於使用中的材質被摧毀了,出現錯誤


使用清除快取的方式處理序列圖重複的方法,
顯然不是正確的處理方式,就不接著討論了


相關討論:


上一篇
[Re:PixiJS - Day27] Loader(2/2) / 解析 JSON 檔與讀取成 PIXI.Spritesheet
下一篇
[Re:PixiJS - Day29] 使用 TexturePacker 製作 AnimatedSprite 與 Sprite 的大圖與 json 檔
系列文
再談 PixiJS,那些先前不一定有提到的部分與地雷45
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言